using Microsoft.Extensions.Logging;
using SeataNet.Core.Configuration;
using SeataNet.Core.RPC;
using SeataNet.Core.Transaction;
using SeataNet.Core.Exceptions;

namespace SeataNet.Core.Services
{
    /// <summary>
    /// Seata服务
    /// </summary>
    public class SeataService : ISeataService, IDisposable
    {
        private readonly IRpcClient _rpcClient;
        private readonly ITransactionManager _transactionManager;
        private readonly IResourceManager _resourceManager;
        private readonly ILogger<SeataService> _logger;
        private readonly SeataConfiguration _configuration;
        private bool _isInitialized = false;
        
        public SeataService(
            IRpcClient rpcClient,
            ITransactionManager transactionManager,
            IResourceManager resourceManager,
            ILogger<SeataService> logger)
        {
            _rpcClient = rpcClient ?? throw new ArgumentNullException(nameof(rpcClient));
            _transactionManager = transactionManager ?? throw new ArgumentNullException(nameof(transactionManager));
            _resourceManager = resourceManager ?? throw new ArgumentNullException(nameof(resourceManager));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _configuration = SeataConfiguration.Instance;
        }
        
        /// <summary>
        /// 初始化Seata服务
        /// </summary>
        public async Task InitializeAsync()
        {
            if (_isInitialized)
            {
                _logger.LogWarning("Seata service is already initialized");
                return;
            }
            
            try
            {
                // 初始化RPC客户端
                var serverAddress = _configuration.Transport.ServerAddress;
                var applicationId = _configuration.ApplicationId;
                var transactionServiceGroup = _configuration.TransactionServiceGroup;
                
                if (string.IsNullOrEmpty(serverAddress))
                {
                    throw new ConfigurationException("Server address is not configured");
                }
                
                if (string.IsNullOrEmpty(applicationId))
                {
                    throw new ConfigurationException("Application ID is not configured");
                }
                
                if (string.IsNullOrEmpty(transactionServiceGroup))
                {
                    throw new ConfigurationException("Transaction service group is not configured");
                }
                
                var success = await _rpcClient.InitializeAsync(serverAddress, applicationId, transactionServiceGroup);
                if (!success)
                {
                    throw new RpcException("Failed to initialize RPC client");
                }
                
                _isInitialized = true;
                _logger.LogInformation("Seata service initialized successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to initialize Seata service");
                throw;
            }
        }
        
        /// <summary>
        /// 销毁Seata服务
        /// </summary>
        public async Task DestroyAsync()
        {
            if (!_isInitialized)
            {
                return;
            }
            
            try
            {
                // 销毁RPC客户端
                await _rpcClient.DestroyAsync();
                
                _isInitialized = false;
                _logger.LogInformation("Seata service destroyed successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to destroy Seata service");
                throw;
            }
        }
        
        /// <summary>
        /// 获取事务管理器
        /// </summary>
        public ITransactionManager GetTransactionManager()
        {
            EnsureInitialized();
            return _transactionManager;
        }
        
        /// <summary>
        /// 获取资源管理器
        /// </summary>
        public IResourceManager GetResourceManager()
        {
            EnsureInitialized();
            return _resourceManager;
        }
        
        /// <summary>
        /// 获取RPC客户端
        /// </summary>
        public IRpcClient GetRpcClient()
        {
            EnsureInitialized();
            return _rpcClient;
        }
        
        /// <summary>
        /// 获取配置
        /// </summary>
        public SeataConfiguration GetConfiguration()
        {
            return _configuration;
        }
        
        /// <summary>
        /// 确保服务已初始化
        /// </summary>
        private void EnsureInitialized()
        {
            if (!_isInitialized)
            {
                throw new InvalidOperationException("Seata service is not initialized");
            }
        }
        
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (_isInitialized)
            {
                try
                {
                    DestroyAsync().GetAwaiter().GetResult();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to destroy Seata service during disposal");
                }
            }
        }
    }
    
    /// <summary>
    /// Seata服务接口
    /// </summary>
    public interface ISeataService
    {
        /// <summary>
        /// 初始化Seata服务
        /// </summary>
        Task InitializeAsync();
        
        /// <summary>
        /// 销毁Seata服务
        /// </summary>
        Task DestroyAsync();
        
        /// <summary>
        /// 获取事务管理器
        /// </summary>
        ITransactionManager GetTransactionManager();
        
        /// <summary>
        /// 获取资源管理器
        /// </summary>
        IResourceManager GetResourceManager();
        
        /// <summary>
        /// 获取RPC客户端
        /// </summary>
        IRpcClient GetRpcClient();
        
        /// <summary>
        /// 获取配置
        /// </summary>
        SeataConfiguration GetConfiguration();
    }
}